package l1j.server.echo;

import java.io.InputStream;
import java.util.logging.Level;
import java.util.logging.Logger;

import l1j.server.Config;
import l1j.server.encryptions.Encryption;
import l1j.server.server.utils.StreamUtil;

/**
 * 封包解密管理
 * @author dexc
 *
 */
public class DecryptExecutor {

	private static final Logger _log = Logger.getLogger(DecryptExecutor.class.getName());

	private final ClientThread _client;

	private final InputStream _in;

	private final Encryption _keys;

	public DecryptExecutor(final ClientThread client, final InputStream in) {
		this._client = client;
		this._keys = client.get_keys();
		this._in = in;
	}

	/**
	 * 客戶端封包解密處理(IO)
	 *
	 * @return
	 * @throws Exception
	 */
	public byte[] decrypt() throws Exception {

		try {
			int hiByte = this._in.read();
			int loByte = this._in.read();

			if (loByte < 0) {
				throw new DecryptErrorException();
			}

			//TODO 伺服器綑綁
			if(Config.LOGINS_TO_AUTOENTICATION) {
				hiByte ^= this._client._xorByte;
				loByte ^= this._client._xorByte;
			}

			final int dataLength = (loByte << 8) + hiByte - 2;

			final byte data[] = new byte[dataLength];

			int readSize = 0;

			for (int i = 0; i != -1 && readSize < dataLength; readSize += i) {
				i = this._in.read(data, readSize, dataLength - readSize);
			}

			if (readSize != dataLength) {
				throw new RuntimeException();
			}

			if(Config.LOGINS_TO_AUTOENTICATION) {
				for(int i = 0; i < dataLength; i++) {
					data[i]=(byte)(data[i] ^ this._client._xorByte);
				}
			}

			return this._keys.decrypt(data);

		} catch (final Exception e) {
			//_log.error(e.getLocalizedMessage(), e);
			throw new DecryptErrorException();
		}
	}

	public ClientThread get_client() {
		return this._client;
	}

	public void stop() {
		try {
			StreamUtil.close(this._in);

		} catch (final Exception e) {
			_log.log(Level.SEVERE ,e.getLocalizedMessage(), e);
		}
	}
}
